import pyautogui
import random
import time
import math
import json
from dataclasses import dataclass, asdict
from typing import Tuple, Optional


@dataclass
class Config:
    red_point: Optional[Tuple[int, int]] = None  # 屏幕坐标(x,y)
    # red_dot_color: Tuple[int, int, int] = (255, 0, 0)
    # white_threshold: float = 0.7
    # check_positions: Optional[List[Tuple[int, int]]] = None

    @classmethod
    def load(cls, filepath: str) -> 'Config':
        """从JSON文件加载配置,文件不存在时返回默认配置"""
        try:
            with open(filepath, 'r') as f:
                data = json.load(f)
                # 转换JSON数组为Python元组
                if 'red_dot_color' in data:
                    data['red_dot_color'] = tuple(data['red_dot_color'])
                if 'check_positions' in data:
                    data['check_positions'] = [tuple(pos) for pos in data['check_positions']]
                return cls(**data)
        except FileNotFoundError:
            return cls()  # 返回默认配置
        except json.JSONDecodeError:
            print(f"Warning: Invalid JSON format in {filepath}")
            return cls()

    def save(self, filepath: str) -> None:
        """保存配置到JSON文件"""
        data = asdict(self)
        with open(filepath, 'w') as f:
            json.dump(data, f, indent=4)


def ensure_in_screen(x, y, screen_size):
    """确保坐标在屏幕范围内"""
    screen_width, screen_height = screen_size
    x = max(0, min(x, screen_width - 1))
    y = max(0, min(y, screen_height - 1))
    return x, y


def ensure_in_screen(x, y, screen_size):
    """确保坐标在屏幕范围内"""
    screen_width, screen_height = screen_size
    x = max(0, min(x, screen_width - 1))
    y = max(0, min(y, screen_height - 1))
    return x, y


def human_like_move(x, y, screen_size):
    """模拟人类鼠标移动轨迹(带加速度)"""
    current_x, current_y = pyautogui.position()
    x, y = ensure_in_screen(x, y, screen_size)

    # 计算总距离(像素)
    distance = math.sqrt((x - current_x) ** 2 + (y - current_y) ** 2)

    # 根据距离计算移动时间(人类平均移动速度约1000像素/秒)
    base_speed = 1000  # 像素/秒
    min_time = 0.3  # 最小移动时间
    max_time = 2.0  # 最大移动时间
    move_time = min(max(distance / base_speed, min_time), max_time)

    # 添加随机性(±30%)
    move_time *= random.uniform(0.7, 1.3)

    # 步数计算(每5像素一步)
    steps = max(10, int(distance / 5))

    # 贝塞尔曲线控制点
    ctrl_x = current_x + (x - current_x) * random.uniform(0.3, 0.7)
    ctrl_y = current_y + (y - current_y) * random.uniform(0.3, 0.7)

    for i in range(steps + 1):
        t = i / steps
        # 加速度曲线：开始慢，中间快，结束慢
        ease_t = 0.5 - 0.5 * math.cos(t * math.pi)

        # 二次贝塞尔曲线
        bezier_x = (1 - ease_t) ** 2 * current_x + 2 * (1 - ease_t) * ease_t * ctrl_x + ease_t**2 * x
        bezier_y = (1 - ease_t) ** 2 * current_y + 2 * (1 - ease_t) * ease_t * ctrl_y + ease_t**2 * y

        # 添加随机偏移并确保在屏幕内
        bezier_x += random.randint(-2, 2)
        bezier_y += random.randint(-2, 2)
        bezier_x, bezier_y = ensure_in_screen(bezier_x, bezier_y, screen_size)

        pyautogui.moveTo(bezier_x, bezier_y, duration=move_time / steps)


def human_like_click(x, y, screen_size):
    """模拟人类点击行为"""
    human_like_move(x, y, screen_size)
    time.sleep(0.1)
    pyautogui.mouseDown(button='left')
    time.sleep(random.uniform(0.05, 0.2))
    pyautogui.mouseUp(button='left')
